package com.stu.interview;

import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * Java 集合面试题代码演示
 * 
 * 本类演示了 Java 集合框架相关的面试题，包括：
 * 1. 集合类型和特点
 * 2. 线程安全性
 * 3. HashMap 原理和实现
 * 4. ArrayList vs LinkedList
 * 5. fail-fast 和 fail-safe 机制
 * 6. 并发集合的使用
 * 
 * @author 高级软件工程师
 * @version 1.0
 * @since JDK 1.8
 */
public class JavaCollectionDemo {

    public static void main(String[] args) {
        System.out.println("=== Java 集合面试题演示 ===");
        
        // 1. 常见集合类型演示
        demonstrateCollectionTypes();
        
        // 2. Comparable 和 Comparator 接口区别
        demonstrateComparableVsComparator();
        
        // 3. Collection 和 Collections 区别
        demonstrateCollectionVsCollections();
        
        // 4. Iterator 和 Enumeration 区别
        demonstrateIteratorVsEnumeration();
        
        // 5. HashMap 原理演示
        demonstrateHashMapPrinciple();
        
        // 6. ArrayList vs LinkedList 性能对比
        demonstrateListPerformance();
        
        // 7. 线程安全集合演示
        demonstrateThreadSafeCollections();
        
        // 8. fail-fast 和 fail-safe 机制
        demonstrateFailFastAndFailSafe();
        
        // 9. ConcurrentHashMap 演示
        demonstrateConcurrentHashMap();
        
        // 10. 集合的不可修改性
        demonstrateUnmodifiableCollections();
    }

    /**
     * 演示常见集合类型和特点
     * 面试题：说说常见的集合有哪些？List、Set、Map 之间的区别是什么？
     */
    private static void demonstrateCollectionTypes() {
        System.out.println("\n1. === 常见集合类型演示 ===");
        
        // List: 有序、可重复
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("Java"); // 允许重复
        System.out.println("List (有序、可重复): " + list);
        
        // Set: 无序、不可重复
        Set<String> set = new HashSet<>();
        set.add("Java");
        set.add("Python");
        set.add("Java"); // 重复元素不会被添加
        System.out.println("Set (无序、不可重复): " + set);
        
        // Map: 键值对存储，键不可重复
        Map<String, Integer> map = new HashMap<>();
        map.put("Java", 25);
        map.put("Python", 30);
        map.put("Java", 28); // 键重复，值会被覆盖
        System.out.println("Map (键值对，键不可重复): " + map);
        
        // 支持随机访问的集合
        System.out.println("\n支持随机访问的集合:");
        System.out.println("ArrayList 实现 RandomAccess 接口: " + (list instanceof RandomAccess));
        System.out.println("LinkedList 实现 RandomAccess 接口: " + (new LinkedList<>() instanceof RandomAccess));
    }

    /**
     * 演示 Comparable 和 Comparator 接口的区别
     * 面试题：Comparable 和 Comparator 接口的区别？
     */
    private static void demonstrateComparableVsComparator() {
        System.out.println("\n2. === Comparable vs Comparator 演示 ===");
        
        // 使用 Comparable 接口（内部比较器）
        List<Student> students1 = Arrays.asList(
            new Student("张三", 85),
            new Student("李四", 92),
            new Student("王五", 78)
        );
        Collections.sort(students1); // 使用 Student 类的 compareTo 方法
        System.out.println("使用 Comparable 按分数排序: " + students1);
        
        // 使用 Comparator 接口（外部比较器）
        List<Student> students2 = Arrays.asList(
            new Student("张三", 85),
            new Student("李四", 92),
            new Student("王五", 78)
        );
        Collections.sort(students2, new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                return s1.getName().compareTo(s2.getName()); // 按姓名排序
            }
        });
        System.out.println("使用 Comparator 按姓名排序: " + students2);
        
        // Java 8 Lambda 表达式简化 Comparator
        students2.sort((s1, s2) -> Integer.compare(s2.getScore(), s1.getScore())); // 按分数降序
        System.out.println("使用 Lambda 按分数降序: " + students2);
    }

    /**
     * 演示 Collection 和 Collections 的区别
     * 面试题：Collection 和 Collections 的区别？
     */
    private static void demonstrateCollectionVsCollections() {
        System.out.println("\n3. === Collection vs Collections 演示 ===");
        
        // Collection 是接口，定义了集合的基本操作
        Collection<String> collection = new ArrayList<>();
        collection.add("元素1");
        collection.add("元素2");
        System.out.println("Collection 接口操作: " + collection);
        
        // Collections 是工具类，提供了操作集合的静态方法
        List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6);
        System.out.println("原始列表: " + numbers);
        
        // Collections 工具类的常用方法
        Collections.sort(numbers); // 排序
        System.out.println("排序后: " + numbers);
        
        Collections.reverse(numbers); // 反转
        System.out.println("反转后: " + numbers);
        
        Collections.shuffle(numbers); // 随机打乱
        System.out.println("打乱后: " + numbers);
        
        System.out.println("最大值: " + Collections.max(numbers));
        System.out.println("最小值: " + Collections.min(numbers));
    }

    /**
     * 演示 Iterator 和 Enumeration 的区别
     * 面试题：Enumeration 和 Iterator 接口的区别？
     */
    private static void demonstrateIteratorVsEnumeration() {
        System.out.println("\n4. === Iterator vs Enumeration 演示 ===");
        
        // Iterator: 现代集合框架的标准迭代器
        List<String> list = Arrays.asList("A", "B", "C", "D");
        System.out.println("使用 Iterator 遍历:");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String element = iterator.next();
            System.out.print(element + " ");
            // iterator.remove(); // Iterator 支持安全删除
        }
        System.out.println();
        
        // Enumeration: 旧版本的迭代器，主要用于 Vector、Hashtable
        Vector<String> vector = new Vector<>(Arrays.asList("X", "Y", "Z"));
        System.out.println("使用 Enumeration 遍历:");
        Enumeration<String> enumeration = vector.elements();
        while (enumeration.hasMoreElements()) {
            String element = enumeration.nextElement();
            System.out.print(element + " ");
            // Enumeration 不支持删除操作
        }
        System.out.println();
        
        System.out.println("\n区别总结:");
        System.out.println("1. Iterator 支持 remove() 操作，Enumeration 不支持");
        System.out.println("2. Iterator 是 fail-fast 的，Enumeration 不是");
        System.out.println("3. Iterator 是现代集合框架的标准，Enumeration 是遗留接口");
    }

    /**
     * 演示 HashMap 的原理和实现
     * 面试题：HashMap 的数据结构是什么？HashMap 的 put/get 方法逻辑？
     */
    private static void demonstrateHashMapPrinciple() {
        System.out.println("\n5. === HashMap 原理演示 ===");
        
        // HashMap 基本操作
        Map<String, Integer> hashMap = new HashMap<>();
        
        // put 操作演示
        System.out.println("HashMap put 操作:");
        hashMap.put("Java", 25);
        hashMap.put("Python", 30);
        hashMap.put("JavaScript", 28);
        hashMap.put("Java", 26); // 键重复，值被覆盖
        System.out.println("HashMap 内容: " + hashMap);
        
        // get 操作演示
        System.out.println("\nHashMap get 操作:");
        System.out.println("Java 的值: " + hashMap.get("Java"));
        System.out.println("C++ 的值: " + hashMap.get("C++")); // 不存在返回 null
        
        // hash 冲突演示
        System.out.println("\nHash 冲突演示:");
        Map<HashConflictKey, String> conflictMap = new HashMap<>();
        HashConflictKey key1 = new HashConflictKey("key1");
        HashConflictKey key2 = new HashConflictKey("key2");
        conflictMap.put(key1, "value1");
        conflictMap.put(key2, "value2");
        System.out.println("冲突键的 hashCode: " + key1.hashCode() + ", " + key2.hashCode());
        System.out.println("冲突映射: " + conflictMap);
        
        // HashMap vs Hashtable 区别演示
        System.out.println("\nHashMap vs Hashtable 区别:");
        Map<String, String> nullTestMap = new HashMap<>();
        Map<String, String> hashtable = new Hashtable<>();
        try {
            nullTestMap.put(null, "null key"); // HashMap 允许 null 键
            nullTestMap.put("null value", null); // HashMap 允许 null 值
            System.out.println("HashMap 允许 null: " + nullTestMap.containsKey(null));
            System.out.println("HashMap 内容: " + nullTestMap);
            
            // hashtable.put(null, "null key"); // Hashtable 不允许 null，会抛异常
        } catch (NullPointerException e) {
            System.out.println("Hashtable 不允许 null 键或值");
        }
    }

    /**
     * 演示 ArrayList 和 LinkedList 的性能对比
     * 面试题：ArrayList 和 LinkedList 的区别？
     */
    private static void demonstrateListPerformance() {
        System.out.println("\n6. === ArrayList vs LinkedList 性能对比 ===");
        
        int size = 100000;
        
        // ArrayList 性能测试
        List<Integer> arrayList = new ArrayList<>();
        long startTime = System.currentTimeMillis();
        
        // 尾部插入测试
        for (int i = 0; i < size; i++) {
            arrayList.add(i);
        }
        long arrayListAddTime = System.currentTimeMillis() - startTime;
        
        // LinkedList 性能测试
        List<Integer> linkedList = new LinkedList<>();
        startTime = System.currentTimeMillis();
        
        for (int i = 0; i < size; i++) {
            linkedList.add(i);
        }
        long linkedListAddTime = System.currentTimeMillis() - startTime;
        
        System.out.println("尾部插入 " + size + " 个元素:");
        System.out.println("ArrayList 耗时: " + arrayListAddTime + "ms");
        System.out.println("LinkedList 耗时: " + linkedListAddTime + "ms");
        
        // 随机访问测试
        startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            arrayList.get(i * 50);
        }
        long arrayListGetTime = System.currentTimeMillis() - startTime;
        
        startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            linkedList.get(i * 50);
        }
        long linkedListGetTime = System.currentTimeMillis() - startTime;
        
        System.out.println("\n随机访问 1000 次:");
        System.out.println("ArrayList 耗时: " + arrayListGetTime + "ms");
        System.out.println("LinkedList 耗时: " + linkedListGetTime + "ms");
        
        System.out.println("\n总结:");
        System.out.println("1. ArrayList 基于数组，随机访问快，插入删除慢（需要移动元素）");
        System.out.println("2. LinkedList 基于双向链表，插入删除快，随机访问慢（需要遍历）");
        System.out.println("3. ArrayList 适合读多写少，LinkedList 适合写多读少");
    }

    /**
     * 演示线程安全的集合
     * 面试题：常用的线程安全的 Map/List 有哪些？
     */
    private static void demonstrateThreadSafeCollections() {
        System.out.println("\n7. === 线程安全集合演示 ===");
        
        // 线程安全的 Map
        System.out.println("线程安全的 Map:");
        Map<String, Integer> synchronizedMap = Collections.synchronizedMap(new HashMap<>());
        Map<String, Integer> concurrentHashMap = new ConcurrentHashMap<>();
        Map<String, Integer> hashtable = new Hashtable<>();
        
        System.out.println("1. Collections.synchronizedMap() - 同步包装器");
        System.out.println("2. ConcurrentHashMap - 分段锁实现");
        System.out.println("3. Hashtable - 方法级同步");
        
        // 线程安全的 List
        System.out.println("\n线程安全的 List:");
        List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>());
        List<String> vector = new Vector<>();
        List<String> copyOnWriteArrayList = new CopyOnWriteArrayList<>();
        
        System.out.println("1. Collections.synchronizedList() - 同步包装器");
        System.out.println("2. Vector - 方法级同步");
        System.out.println("3. CopyOnWriteArrayList - 写时复制");
        
        // CopyOnWriteArrayList 特点演示
        System.out.println("\nCopyOnWriteArrayList 特点:");
        copyOnWriteArrayList.add("元素1");
        copyOnWriteArrayList.add("元素2");
        
        // 迭代过程中修改不会抛异常
        for (String item : copyOnWriteArrayList) {
            System.out.println("读取: " + item);
            copyOnWriteArrayList.add("新元素"); // 写时复制，不影响当前迭代
        }
        System.out.println("最终内容: " + copyOnWriteArrayList);
    }

    /**
     * 演示 fail-fast 和 fail-safe 机制
     * 面试题：什么是 fail-fast？什么是 fail-safe？fail-fast 与 fail-safe 有什么区别？
     */
    private static void demonstrateFailFastAndFailSafe() {
        System.out.println("\n8. === fail-fast 和 fail-safe 机制演示 ===");
        
        // fail-fast 演示（ArrayList）
        System.out.println("fail-fast 演示 (ArrayList):");
        List<String> failFastList = new ArrayList<>(Arrays.asList("A", "B", "C", "D"));
        
        try {
            for (String item : failFastList) {
                System.out.println("处理: " + item);
                if ("B".equals(item)) {
                    failFastList.remove(item); // 修改集合，触发 ConcurrentModificationException
                }
            }
        } catch (ConcurrentModificationException e) {
            System.out.println("捕获到 ConcurrentModificationException: " + e.getMessage());
        }
        
        // fail-safe 演示（CopyOnWriteArrayList）
        System.out.println("\nfail-safe 演示 (CopyOnWriteArrayList):");
        List<String> failSafeList = new CopyOnWriteArrayList<>(Arrays.asList("X", "Y", "Z"));
        
        for (String item : failSafeList) {
            System.out.println("处理: " + item);
            if ("Y".equals(item)) {
                failSafeList.remove(item); // 不会抛异常，但迭代器看到的是快照
            }
        }
        System.out.println("最终内容: " + failSafeList);
        
        // 正确的删除方式
        System.out.println("\n正确的删除方式 (使用 Iterator):");
        List<String> correctList = new ArrayList<>(Arrays.asList("1", "2", "3", "4"));
        Iterator<String> iterator = correctList.iterator();
        while (iterator.hasNext()) {
            String item = iterator.next();
            if ("2".equals(item) || "3".equals(item)) {
                iterator.remove(); // 使用迭代器的 remove 方法
            }
        }
        System.out.println("删除后: " + correctList);
    }

    /**
     * 演示 ConcurrentHashMap 的特点
     * 面试题：ConcurrentHashMap 的数据结构？
     */
    private static void demonstrateConcurrentHashMap() {
        System.out.println("\n9. === ConcurrentHashMap 演示 ===");
        
        ConcurrentHashMap<String, Integer> concurrentMap = new ConcurrentHashMap<>();
        
        // 基本操作
        concurrentMap.put("Java", 1);
        concurrentMap.put("Python", 2);
        concurrentMap.put("JavaScript", 3);
        
        System.out.println("ConcurrentHashMap 内容: " + concurrentMap);
        
        // 原子操作演示
        System.out.println("\n原子操作演示:");
        
        // putIfAbsent - 如果不存在则放入
        Integer oldValue = concurrentMap.putIfAbsent("C++", 4);
        System.out.println("putIfAbsent C++: " + oldValue + ", 当前值: " + concurrentMap.get("C++"));
        
        oldValue = concurrentMap.putIfAbsent("Java", 10); // Java 已存在
        System.out.println("putIfAbsent Java: " + oldValue + ", 当前值: " + concurrentMap.get("Java"));
        
        // replace - 替换
        boolean replaced = concurrentMap.replace("Python", 2, 20);
        System.out.println("replace Python 2->20: " + replaced + ", 当前值: " + concurrentMap.get("Python"));
        
        // compute - 计算新值
        concurrentMap.compute("Java", (key, val) -> val == null ? 1 : val + 1);
        System.out.println("compute Java +1: " + concurrentMap.get("Java"));
        
        // merge - 合并值
        concurrentMap.merge("Go", 1, Integer::sum);
        concurrentMap.merge("Go", 2, Integer::sum);
        System.out.println("merge Go: " + concurrentMap.get("Go"));
        
        System.out.println("\nConcurrentHashMap 特点:");
        System.out.println("1. JDK 7: 分段锁 (Segment)");
        System.out.println("2. JDK 8: CAS + synchronized (Node)");
        System.out.println("3. 支持高并发读写");
        System.out.println("4. 提供原子操作方法");
    }

    /**
     * 演示不可修改的集合
     * 面试题：怎么确保一个集合不能被修改？
     */
    private static void demonstrateUnmodifiableCollections() {
        System.out.println("\n10. === 不可修改集合演示 ===");
        
        // 创建可修改的集合
        List<String> mutableList = new ArrayList<>(Arrays.asList("A", "B", "C"));
        Set<String> mutableSet = new HashSet<>(Arrays.asList("X", "Y", "Z"));
        Map<String, Integer> mutableMap = new HashMap<>();
        mutableMap.put("one", 1);
        mutableMap.put("two", 2);
        
        // 创建不可修改的集合
        List<String> unmodifiableList = Collections.unmodifiableList(mutableList);
        Set<String> unmodifiableSet = Collections.unmodifiableSet(mutableSet);
        Map<String, Integer> unmodifiableMap = Collections.unmodifiableMap(mutableMap);
        
        System.out.println("不可修改的 List: " + unmodifiableList);
        System.out.println("不可修改的 Set: " + unmodifiableSet);
        System.out.println("不可修改的 Map: " + unmodifiableMap);
        
        // 尝试修改不可修改的集合
        try {
            unmodifiableList.add("D");
        } catch (UnsupportedOperationException e) {
            System.out.println("\n尝试修改不可修改的 List: " + e.getClass().getSimpleName());
        }
        
        // 注意：原始集合的修改会影响不可修改的视图
        System.out.println("\n修改原始集合前: " + unmodifiableList);
        mutableList.add("D");
        System.out.println("修改原始集合后: " + unmodifiableList);
        
        // Java 9+ 的不可变集合（真正不可变）
        System.out.println("\nJava 9+ 不可变集合:");
        // List<String> immutableList = List.of("A", "B", "C"); // Java 9+
        // Set<String> immutableSet = Set.of("X", "Y", "Z"); // Java 9+
        // Map<String, Integer> immutableMap = Map.of("one", 1, "two", 2); // Java 9+
        
        System.out.println("确保集合不可修改的方法:");
        System.out.println("1. Collections.unmodifiableXxx() - 创建不可修改视图");
        System.out.println("2. Java 9+ List.of(), Set.of(), Map.of() - 创建真正不可变集合");
        System.out.println("3. Google Guava ImmutableList, ImmutableSet, ImmutableMap");
        System.out.println("4. 防御性复制 - 返回集合的副本");
    }

    /**
     * 学生类，实现 Comparable 接口
     * 用于演示 Comparable 和 Comparator 的区别
     */
    static class Student implements Comparable<Student> {
        private String name;
        private int score;

        public Student(String name, int score) {
            this.name = name;
            this.score = score;
        }

        @Override
        public int compareTo(Student other) {
            // 按分数升序排序
            return Integer.compare(this.score, other.score);
        }

        public String getName() {
            return name;
        }

        public int getScore() {
            return score;
        }

        @Override
        public String toString() {
            return name + "(" + score + ")";
        }
    }

    /**
     * Hash 冲突演示类
     * 故意让不同对象产生相同的 hashCode
     */
    static class HashConflictKey {
        private String key;

        public HashConflictKey(String key) {
            this.key = key;
        }

        @Override
        public int hashCode() {
            // 故意返回固定值，制造 hash 冲突
            return 42;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null || getClass() != obj.getClass()) return false;
            HashConflictKey that = (HashConflictKey) obj;
            return Objects.equals(key, that.key);
        }

        @Override
        public String toString() {
            return key;
        }
    }
}